#include "../logs/log_sys.h"
#include <vector>
#include <thread>
#include <chrono>

void bench(const std::string &loggername, size_t thread_count, size_t msg_count, size_t msg_len)
{
    // 1. 获取日志器
    log_sys::Logger::ptr logger = log_sys::getlogger(loggername);
    if (logger.get() == nullptr)
    {
        return;
    }
    
    // 2. 组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A'); // 最后一个字符是换行符作为打印

    std::cout << "测试日志：" << msg_count << "条，总大小: " << (msg_count * msg_len) / 1024 << "KB\n";

    // 3. 创建指定数量的线程
    std::vector<std::thread> threads;
    std::vector<double> cost_array(thread_count);
    size_t lognum_in_a_thread = msg_count / thread_count; // 总日志数量除以线程数量，得到每个线程处理的 日志数量
    for (int i = 0; i < thread_count; i++) {
        threads.emplace_back([&, i]() {
            // 4. 线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            // 5. 开始循环写日志
            for(int j = 0; j < lognum_in_a_thread; j++)
            {
                logger->fatal("%s", msg.c_str());
            }

            // 6. 线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_array[i] = cost.count();
            std::cout << "线程" << i << ": " << "\t输出日志数量: " << lognum_in_a_thread << ", 耗时：" << cost.count() << "s" << std::endl;
        });
    }
    
    for (int i = 0; i < thread_count; i++)
    {
        threads[i].join();
    }
    
    // 7. 计算总耗时: 在多线程中，每个线程都会耗费时间，但是线程是并发处理的，因此耗时最高的那个线程消耗的时间称为总时间
    double max_cost = cost_array[0];
    for(int i = 0; i < thread_count; i++)
    {
        max_cost = max_cost < cost_array[i] ? cost_array[i] : max_cost;        
    }
    size_t log_output_num_in_a_sec = msg_count / max_cost;
    size_t size_output_num_in_a_sec = (msg_count * msg_len) / (max_cost * 1024);
    // 8. 输出打印
    std::cout << "每秒输出日志数量：" << log_output_num_in_a_sec << "条\n";
    std::cout << "每秒输出日志大小：" << size_output_num_in_a_sec << "KB\n";

}

void sync_bench()
{
    std::unique_ptr<log_sys::loggerBuilder> builder(new log_sys::GlobalLoggerBuilder());
    builder->NameBuilder("sy");
    // builder->LevelBuilder(log_sys::Log_level::Value::DEBUG);
    builder->FormatBuilder("%m%n");
    builder->TypeBuilder(log_sys::LoggerType::SYNC_LOGGER);
    // builder->ChangeUnsafeAsyncBuilder(); 
    builder->SinkBuilder<log_sys::FileSink>("./logfile/sync.log");
    // builder->SinkBuilder<log_sys::RollBySizeSink>("./logfile/roll-sync.log-by-size", 1024 * 1024);
    builder->build();
    // bench("sy", 1, 1000000, 100);
    bench("sy", 3, 1000000, 100);
}

void async_bench()
{
    std::unique_ptr<log_sys::loggerBuilder> builder(new log_sys::GlobalLoggerBuilder());
    builder->NameBuilder("asy");
    builder->LevelBuilder(log_sys::Log_level::Value::DEBUG);
    builder->FormatBuilder("%m%n");
    builder->TypeBuilder(log_sys::LoggerType::ASYNC_LOGGER);
    builder->ChangeUnsafeAsyncBuilder(); 
    builder->SinkBuilder<log_sys::FileSink>("./logfile/async.log");
    // builder->SinkBuilder<log_sys::RollBySizeSink>("./logfile/roll-sync.log-by-size", 1024 * 1024);
    builder->build();
    // bench("asy", 1, 1000000, 100);
    bench("asy", 3, 1000000, 100);
}

int main()
{
    // sync_bench();
    async_bench();
    return 0;
}
